package com.small.nacos.naming.controllers;

import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.naming.CommonParams;
import com.alibaba.nacos.api.naming.utils.NamingUtils;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.small.nacos.naming.core.Instance;
import com.small.nacos.naming.core.Service;
import com.small.nacos.naming.core.ServiceManager;
import com.small.nacos.naming.core.utils.WebUtils;
import com.small.nacos.naming.misc.UtilsAndCommons;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @Author zhoujin
 * @Date 2022/7/22 20:48
 */
@RestController
@RequestMapping(UtilsAndCommons.NACOS_NAMING_CONTEXT + "/instance")
public class InstanceController {

    @Autowired
    private ServiceManager serviceManager;

    @PostMapping
    public String register(HttpServletRequest request) throws Exception {

        final String namespaceId = request.getParameter(CommonParams.NAMESPACE_ID);
        final String serviceName = request.getParameter(CommonParams.SERVICE_NAME);
        final Instance instance = parseInstance(request);

        serviceManager.registerInstance(namespaceId, serviceName, instance);
        return "ok";
    }

    @GetMapping("/list")
    public ObjectNode list(HttpServletRequest request) throws Exception {

        String namespaceId = WebUtils.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
        String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
        String clusters = WebUtils.optional(request, "clusters", StringUtils.EMPTY);
        return doSrvIpxt(namespaceId, serviceName,clusters);
    }

    private ObjectNode doSrvIpxt(String namespaceId, String serviceName,String clusters) {

        Service service = serviceManager.getService(namespaceId, serviceName);
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        if (service == null){
            result.put("name", serviceName);
            result.replace("hosts", JacksonUtils.createEmptyArrayNode());
            return result;
        }

        List<Instance> srvedIPs = service.srvIPs(Arrays.asList(StringUtils.split(clusters, ",")));

        ArrayNode hosts = JacksonUtils.createEmptyArrayNode();

        for (Instance instance : srvedIPs) {

            ObjectNode ipObj = JacksonUtils.createEmptyJsonNode();
            ipObj.put("ip", instance.getIp());
            ipObj.put("port", instance.getPort());
            ipObj.put("clusterName", instance.getClusterName());
            ipObj.put("instanceId", instance.getInstanceId());
            ipObj.put("serviceName", instance.getServiceName());
            hosts.add(ipObj);

        }
        result.put("name", serviceName);
        result.replace("hosts", hosts);
        return result;
    }


    /**
     * 解析实例
     * @param request
     * @return
     * @throws Exception
     */
    private Instance parseInstance(HttpServletRequest request){

        String serviceName =request.getParameter(CommonParams.SERVICE_NAME);
        Instance instance = getIpAddress(request);
        instance.setServiceName(serviceName);
        instance.setClusterName(WebUtils.optional(request, CommonParams.CLUSTER_NAME, UtilsAndCommons.DEFAULT_CLUSTER_NAME));
        instance.setInstanceId(instance.generateInstanceId());
        instance.setLastBeat(System.currentTimeMillis());
        return instance;
    }

    private Instance getIpAddress(HttpServletRequest request) {

        boolean enabled = Boolean.parseBoolean(WebUtils.optional(request, "enabled", StringUtils.EMPTY));
        String weight = WebUtils.optional(request, "weight", "1");
        boolean healthy = Boolean.parseBoolean(WebUtils.optional(request, "healthy", "true"));
        Instance instance = getBasicIpAddress(request);
        instance.setWeight(Double.parseDouble(weight));
        instance.setHealthy(healthy);
        instance.setEnabled(enabled);
        return instance;
    }

    private Instance getBasicIpAddress(HttpServletRequest request) {

        final String ip = WebUtils.required(request, "ip");
        final String port = WebUtils.required(request, "port");
        boolean ephemeral = Boolean.parseBoolean(WebUtils.optional(request, "ephemeral", "true"));
        Instance instance = new Instance();
        instance.setPort(Integer.parseInt(port));
        instance.setIp(ip);
        instance.setEphemeral(ephemeral);
        return instance;
    }

}
